import { select, selectAll } from 'd3-selection'
import { drag as d3Drag } from 'd3-drag'
import mitter from '@/mitt'
import { getTopicNodeRect } from '../utils/size'

let svg = null
let container = null
let dragIng = false
let dragMovePosition = { x: 0, y: 0 }

export function graphLengendContainer (svgEl, mindContainer) {
  container = mindContainer
    .append('g')
    .attr('class', 'mind-map-lengend')
    .on('dblclick', event => event.stopPropagation())
  svg = svgEl
}

export function graphLengends (lengend, rootTopic) {
  container.select('foreignObject').remove()
  const { markers = [], position, visibility } = lengend || {}
  if (!visibility) return
  container.attr('transform', `translate(${position.x}, ${position.y})`)
  const existMarkers = getTopicMarkerIcon(rootTopic)
  const lendgends = existMarkers.map(icon => ({ icon, name: markers[icon] }))
  const { width, height } = getContainerSize(lendgends)
  container.append('foreignObject')
    .attr('width', width)
    .attr('height', height)
    .append('xhtml:div')
    .attr('xmlns', 'http://www.w3.org/1999/xhtml')
    .attr('class', 'lengend-box')
    .style('border-radius', '8px')
    .style('padding', '0 10px 8px')
    .style('border', '1px solid #e5dbdb')
    .style('background', 'rgba(255,255,255,0.5)')
    .append('p')
    .text('图例')
    .attr('style', 'text-align: center; color: #000; margin: 0; font-size: 14px; line-height: 38px; border-bottom: 1px solid #e5dbdb;')
    .call(
      d3Drag()
        .on('drag', function (event) {
          if ((event.dx !== 0 || event.dy !== 0) && !dragIng) {
            dragIng = true
            dragMovePosition = { x: event.x, y: event.y }
            container.style('opacity', 0.6)
            svg.classed('grabbing', true)
          }
          if (dragIng) {
            position.x -= (dragMovePosition.x - event.x)
            position.y -= (dragMovePosition.y - event.y)
            container.attr('transform', `translate(${position.x}, ${position.y})`)
          }
        })
        .on('end', function () {
          dragIng = false
          container.style('opacity', 1)
          svg.classed('grabbing', false)
          mitter.emit('set-lengend-position', position)
        }))
    .each(function () {
      select(this.parentNode).append('div')
        .style('margin-top', '8px')
        .html(generateLengendHtmlString(lendgends))
      selectAll('.lengend-editable-item').on('mousedown', event => event.stopPropagation())
        .on('blur', function () {
          const node = select(this).node()
          mitter.emit('set-lengend-name', {
            text: node.innerText,
            icon: node.getAttribute('data-marker')
          })
        })
    })
}

/**
 * 找出主题内所包含的marker icon集合并且去重
 * @param {*} root
 * @returns
 */
function getTopicMarkerIcon (root) {
  const cache = []
  function c (root, cache) {
    if (root.marks?.length) {
      root.marks.forEach(m => {
        cache.push(m.icon)
      })
    }
    if (root.children?.length) {
      root.children.forEach(child => {
        c(child, cache)
      })
    }
  }
  c(root, cache)

  return [...new Set(cache)]
}

function generateLengendHtmlString (lendgends) {
  if (!lendgends.length) {
    return `<div style="font-size: 0; padding-top: 10px">
      <img src="" alt="" />
      <p style="line-height: 24px; font-size: 13px; color: #adb9b9; text-align: center; margin-top: 10px">将图标插入至主题中</p>
    </div>`
  }
  return lendgends.reduce((prev, cur) => {
    prev += `<div style="display: flex; align-items: center; height: 26px; font-size: 0;">
      <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024" width="16" height="16" style="background: #fff; border-radius: 50%; flex-shrink: 0">
        ${select(`#${cur.icon}`).node().innerHTML}
      </svg>
      <div class="lengend-editable-item" contenteditable="true" data-marker="${cur.icon}" style="margin-left: 8px; outline: none; font-size: 14px; font-family: nevermind; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; width: 0;">${cur.name}</div>
    </div>`

    return prev
  }, '')
}

function getContainerSize (lendgends) {
  const height = 38 + 8 + 8 + (lendgends.length ? lendgends.length * 26 : 86) + 8 + 4
  const markerWidths = lendgends.map(o => {
    return getTopicNodeRect({
      fontFamily: 'nevermind',
      fontSize: 14,
      maxWidth: '230px',
      text: o.name
    }).width
  })
  const width = Math.max(Math.max(...markerWidths) + 8 + 20 + 16 + 4, 156)

  return { width, height }
}
